package com.datang.litejvm.cmd;


import com.datang.litejvm.constant.ConstantFieldRefInfo;
import com.datang.litejvm.constant.ConstantPool;
import com.datang.litejvm.engin.ExecutionResult;
import com.datang.litejvm.engin.JavaObject;
import com.datang.litejvm.engin.StackFrame;

public class GetFieldCmd extends TwoOperandCmd {
    public GetFieldCmd(ConstantPool pool, String opCode) {
        super(pool,opCode);
    }

    @Override
    public String toString() {
        return super.toString();
    }

    /**
     * @author: 顶风少年
     * @Description: 获取对象的字段值
     * objectref 必须是一个 reference 类型的数据，在指令执行时，objectref
     * 将从操作数栈中出栈。无符号数 indexbyte1 和 indexbyte2 用于构建一个
     * 当前类（§2.6）的运行时常量池的索引值，构建方式为（indexbyte1 << 8）
     * | indexbyte2，该索引所指向的运行时常量池项应当是一个字段（§5.1）
     * 的符号引用，它包含了字段的名称和描述符，以及包含该字段的类的符号引用。
     * 这个字段的符号引用是已被解析过的（§5.4.3.2）。指令执行后，被
     * objectref 所引用的对象中该字段的值将会被取出，并推入到操作数栈顶。
     * objectref 所引用的对象不能是数组类型，如果取值的字段是 protected
     * 的（§4.6），并且这个字段是当前类的父类成员，并且这个字段没有在同一个
     * 运行时包（§5.3）中定义过，那 objectref 所指向的对象的类型必须为当
     * 前类或者当前类的子类。
     * @date: 17:04 2022/6/17
     **/
    @Override
    public void execute(StackFrame frame, ExecutionResult result) {
        ConstantFieldRefInfo fieldRef = (ConstantFieldRefInfo)this.getConstantInfo(this.getIndex());
        String fieldName = fieldRef.getFieldName();
        JavaObject javaObject = frame.getOperandStack().pop();
        JavaObject fieldValue = javaObject.getFieldValue(fieldName);
        frame.getOperandStack().push(fieldValue);
    }
}
